home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Just Call Me Internet
/
Just Call Me Internet.iso
/
prog
/
atari
/
c
/
nos042_s
/
st_asy.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-09-16
|
13KB
|
485 lines
/*
serial device interface for Atari ST
v0.00 01.01.93 DFN Initial Version
*/
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <osbind.h>
#include "global.h"
#include "config.h"
#include "mbuf.h"
#include "internet.h"
#include "iface.h"
#include "st.h"
#include "cmdparse.h"
#include "asy.h"
#include "st_asy.h"
#include "devparam.h"
struct asy Asy[ASY_MAX];
void __asy_rxover(void);
void __asy_txover(void);
void __stdargs asy_tx(int dev, void *p1, void *p2);
void asy_flush(int dev);
void (*rxover)();
void (*txover)();
void int_rxover(void);
void int_txover(void);
/* Interface list header */
int Nasy = 0; /* number of async devices */
int TX_pwait = 0;
/*
asy_init - Initialize async port "dev"
*/
int asy_init(int dev,
struct iface *iface,
char *addr,
char *vec,
int16 bufsize,
int trigchar,
char monitor,
long speed)
{
char *ifn;
char *bufp_in, *bufp_out;
struct iorec *ip;
struct asy *asy;
Nasy++;
asy = &Asy[dev];
asy->iface = iface; /* link up to interface structure */
asy->rxchar = 0;
asy->txchar = 0;
asy->rxover = 0;
asy->txover = 0;
asy->mode = trigchar;
asy->input_active = 0;
asy->device_name = strdup(addr);
asy->unit = atoi(vec);
asy->buflen = bufsize;
asy->vec = atoi(vec); /* dev to resend bytes to */
asy->addr = 1;
/*
force user to allocate more memory than he already has.
If no memory is allocated, asy_stop() may behave funny...
*/
if (bufsize <= 256) /* only allocate a bigger buffer */
return -1;
if ((bufp_in = malloc(bufsize)) == NULLCHAR){
printf("asy_init(%d): no memory for rx buffer \n", dev);
return -1;
}
if ((bufp_out = malloc(bufsize)) == NULLCHAR){
printf("asy_init(%d): no memory for tx buffer \n", dev);
return -1;
}
/* Save original IOREC values */
ip = Iorec((asy->addr)-1); /* Iorec wants AUX: = 0, MIDI = 2 */
Jdisint(12); /* disable RS-232 interrupt */
asy->in = ip;
memcpy(&asy->oldin, ip, sizeof(struct iorec));
if (asy->addr == RS232) { /* increase RS-232 transmit buffer? */
ip++;
asy->out = ip;
memcpy(&asy->oldout,ip,sizeof(struct iorec));
}
/* Set up receiver FIFO */
asy->in->ibuf = bufp_in; /* buffer pointer */
asy->in->ibufsiz = bufsize; /* size */
asy->in->ibufhd = asy->in->ibuftl = 0; /* head & tail indices */
asy->in->ibuflow = bufsize / 4; /* low water mark */
asy->in->ibufhi = bufsize - (bufsize / 4); /* high water mark */
#if 0
asy->out->ibuf = bufp_out; /* buffer pointer */
asy->out->ibufsiz = bufsize; /* size */
asy->out->ibufhd = asy->out->ibuftl = 0; /* head & tail indices */
asy->out->ibuflow = bufsize / 4; /* low water mark */
asy->out->ibufhi = bufsize - (bufsize / 4); /* high water mark */
#endif
txover = Setexc(73, int_txover); /* link in overrun handlers */
rxover = Setexc(75, int_rxover);
Jenabint(12); /* enable RS-232 interrupts */
Offgibit(0xEF); /* raise DTR */
asy->input_len = 0; /* clear input buffer */
asy->input_active = 0;
asy->serial_open = 1;
asy->output_active = 0;
asy_speed(dev, speed);
iface->txproc = newproc( ifn = if_name(iface," tx"), /* tx thread */
256, asy_tx, dev, iface, NULL, 0);
return (int)Nasy;
}
/*****************************************************************************
asy_stop - restore old iorec and frees memory allocated to the RS-232
buffers. Cycle DTR to force modem to drop the line.
*****************************************************************************/
int asy_stop(struct iface *iface)
{
struct asy *asy;
asy = &Asy[iface->dev];
#ifdef DEBUG
printf("asy_stop: iface=0x%lx dev=%d \n", iface, iface->dev);
fflush(stdout);
#endif
(void)Jdisint(12); /* disable RS-232 interrupts */
Setexc(73, txover); /* restore overrun handlers */
Setexc(75, rxover);
free(asy->in->ibuf); /* free the buffer */
/* Restore old iorecs */
memcpy(asy->in, &asy->oldin, sizeof(struct iorec));
if (asy->addr == RS232) {
int32 t; /* temporary timer variable */
memcpy(asy->out, &asy->oldout, sizeof(struct iorec));
Ongibit(0x10); /* drop DTR, so modem drops line */
t = 500 + msclock(); /* get time + 500ms */
while (t > msclock()) /* wait */
;
Offgibit(0xEF); /* raise DTR */
}
(void)Jenabint(12); /* enable RS-232 interrupts */
Nasy--;
return 0;
}
/*****************************************************************************
asy_speed - Set async line speed
*****************************************************************************/
int asy_speed(int dev, long speed)
{
int baud; /* int result; */
struct asy *asy;
asy = &Asy[dev];
if (speed <= 0 || dev >= Nasy)
return -1;
asy->speed = speed; /* shouldn't this be done in slip.c? */
switch (speed) {
case 300:
baud = 9; /* how slow can you get? :-) */
break;
case 1200:
baud = 7;
break;
case 2400:
baud = 4;
break;
case 4800:
baud = 2;
break;
case 9600:
baud = 1;
break;
case 19200:
baud = 0;
break;
case 38400:
Rsconf(0,2,0x08,-1,-1,-1);
Xbtimer(3,1,8,(void *)-1);
asy_flush(dev);
return 0;
default:
printf("asy_speed: unknown RS-232 speed (%d).\n", speed);
return -1;
}
/* (void) Rsconf(baud,0,0x88,-1,-1,-1); */ /* no flow control */
(void) Rsconf(baud,2,0x88,-1,-1,-1); /* RTS/CTS enabled */
asy_flush(dev);
return 0;
}
/*****************************************************************************
asy_flush - flush the input buffer of device dev (either aux: or midi)
May be useful, because setting the baudrate causes an 0x7f to be sent.
*****************************************************************************/
void asy_flush(int dev)
{
int st_dev;
long c; /* Bconin returns a long */
struct asy *asy = &Asy[dev];
st_dev = asy->addr;
while (Bconstat(st_dev) == -1) { /* at least 1 char available */
c = Bconin(st_dev); /* read character */
}
}
/*****************************************************************************
asy_ioctl - Async line control
*****************************************************************************/
int32 asy_ioctl (struct iface *iface, int cmd, int set, int32 val)
{
int32 retval;
struct asy *asy;
asy = &Asy[iface->dev];
switch (cmd) {
case PARAM_SPEED:
if (set)
asy_speed(iface->dev, val);
return Asy[iface->dev].speed;
case PARAM_DTR:
if (set) {
val ? Offgibit(0xEF) : Ongibit(0x10);
asy->dtr_usage = (val) ? MOVED_UP : MOVED_DOWN;
}
retval = Giaccess(0, 0x0E) & 0x10; /* get DTR status */
tprintf("DTR is %s \n", retval ? "DOWN" : "UP");
return retval ? 0 : 1;
case PARAM_RTS:
if (set) {
val ? Offgibit(0xF7) : Ongibit(0x08);
asy->rts_usage = (val) ? MOVED_UP : MOVED_DOWN;
}
retval = Giaccess(0, 0x0E) & 0x08; /* get RTS status */
tprintf("RTS is %s \n", retval ? "DOWN" : "UP");
return retval ? 0 : 1;
case PARAM_UP:
Offgibit(0xF7); /* raise RTS */
Offgibit(0xEF); /* raise DTR */
asy->rts_usage = MOVED_UP;
asy->dtr_usage = MOVED_UP;
return TRUE;
case PARAM_DOWN:
Ongibit(0x08); /* drop RTS */
Ongibit(0x10); /* drop DTR */
asy->rts_usage = MOVED_DOWN;
asy->dtr_usage = MOVED_DOWN;
return FALSE;
}
return FALSE;
}
/***********************************************************************
asy_rxover - RS232 receiver overrun interrupt handler
***********************************************************************/
void __saveds asy_rxover(void)
{
struct asy *asy = &Asy[0];
asy->rxover = asy->rxover + 1;
}
/***********************************************************************
asy_txover - RS232 transmitter overrun interrupt handler
***********************************************************************/
void __saveds asy_txover(void)
{
struct asy *asy = &Asy[0];
asy->txover = asy->txover + 1;
}
/*****************************************************************************
get_asy - Receive character from asynch line, called from slip.c
Blocks if no character available. Returns -1 if pwait is
interrupted.
*****************************************************************************/
int get_asy(int dev)
{
struct asy *asy = &Asy[dev];
while (Bconstat(asy->addr) == 0) /* 0 - no char, -1 char available */
if (pwait(NULL) != 0) /* giveup the CPU if no char */
return -1; /* signal received */
asy->input_len--;
asy->rxchar++; /* total number of chars received */
return Bconin(asy->addr); /* return i/p character */
}
/*****************************************************************************
asy_len - get length of async input queue
returns 1 if characters are available, else 0
*****************************************************************************/
int asy_len(int dev)
{
struct asy *asy = &Asy[dev];
if (Bconstat(asy->addr) == 0) /* 0 - no char, -1 char available */
return 0; /* no characters waiting */
else
return 1; /* 1 or more characters waiting */
}
/*****************************************************************************
asy_send - queue an mbuf to the async device, called from slip.c
*****************************************************************************/
int asy_send(int dev, struct mbuf *bp)
{
if (dev < 0 || dev >= Nasy)
return -1;
enqueue(&Asy[dev].sndq, bp);
return 0;
}
/*****************************************************************************
asy_tx - send mbufs to the serial device
*****************************************************************************/
void __stdargs asy_tx(int dev, void *p1, void *p2)
{
int st_dev;
unsigned short i = 0;
struct mbuf *bp;
struct asy *asy = &Asy[dev];
st_dev = asy->addr;
for( ; ;) {
while (asy->sndq == NULLBUF)
pwait(&asy->sndq);
bp = dequeue(&asy->sndq);
if (bp != NULLBUF) {
for (i = 0; i < bp->cnt; ++i) {
while (Bcostat(st_dev) == 0) { /* if serial device not ready */
TX_pwait += 1; /* inc the wait count */
pwait(NULL); /* giveup the CPU */
}
(void)Bconout(st_dev, bp->data[i]); /* xmit byte 1= AUX: 3=MIDI: */
}
asy->txchar += bp->cnt; /* increase count of tx chars */
}
bp = free_mbuf(bp); /* do next buf on chain */
}
}
int stxrdy(int dev)
{
return Asy[dev].output_active == 0;
}
static void asyinfo(struct asy *asy, int verbose)
{
short tx_head, tx_tail;
short rx_head, rx_tail;
short chars_in, chars_out;
tx_head = asy->out->ibufhd; /* transmitter head pointer */
tx_tail = asy->out->ibuftl; /* transmiter tail pointer */
rx_head = asy->in->ibufhd; /* receiver head pointer */
rx_tail = asy->in->ibuftl; /* receiver tail pointer */
if ((chars_in = rx_head - rx_tail) < 0)
chars_in = asy->in->ibufsiz - rx_tail + rx_head;
if ((chars_out = tx_head - tx_tail) < 0)
chars_out = asy->out->ibufsiz - tx_tail + tx_head;
tprintf("%s: %8d baud (%s unit %d)\n",
asy->iface->name, asy->speed, asy->device_name, asy->unit);
tprintf(" RX: %8lu chars %8lu o/r %6d in buf (H=%d T=%d B=%d)\n",
asy->rxchar, asy->rxover, chars_in,
asy->in->ibufhd, asy->in->ibuftl, asy->in->ibufsiz);
tprintf(" TX: %8lu chars %8lu o/r %6d in buf (H=%d T=%d B=%d)\n",
asy->txchar, asy->txover, chars_out,
asy->out->ibufhd, asy->out->ibuftl, asy->out->ibufsiz);
tprintf(" pwait = %d \n", TX_pwait);
}
/*****************************************************************************
doasystat -
*****************************************************************************/
int doasystat(int argc, char *argv[], void *envp)
{
struct asy *asy;
int i;
if (!Nasy) {
tprintf("No asy interfaces attached.\n");
return -1;
}
if (argc> 1) {
for (i = 1; i < argc; i++) {
struct asy *dev = NULL;
for (asy = &Asy[0]; asy < &Asy[Nasy]; asy++) {
if (strcmp(asy->iface->name, argv[i]) == 0) {
dev = asy;
break;
}
}
if (dev)
asyinfo(dev, 1);
else
tprintf("Unknown device '%s'\n", argv[i]);
}
} else
/* just dump them all out */
for (asy = &Asy[0]; asy < &Asy[Nasy]; asy++)
asyinfo(asy, 0);
}